#pragma once

#include "Point3F.h"
#include "defines.h"

#include <stdlib.h>

// TEEM
#include <teem/nrrd.h>
#include <teem/biff.h>





class CHOT
{
public:
	float *m_pHOT;
	uint m_w;
	uint m_h;
	uint m_d;
	uint m_n;			// 15 for 4th order tensor, 28 for 6th order tensor
	uint m_order;		// 4 or 6

public:
	CHOT(void);
	~CHOT(void);

public:
	// open the HOT in Nrrd format
	int OpenHOTFile(const char *pathname, FILE *fp = stdout);
	// save the HOT as Nrrd format
	int SaveDTIFile(const char *pathname, FILE *fp = stdout);

	// return the pointer of the HOT data
	float *GetHOTData() { return m_pHOT; }

	// use the following interface to get the HOT value
	// of a particular position in the volume
	void GetHOT(const uint x, const uint y, const uint z, float *hot) const;
	void GetHOT(const float x, const float y, const float z, float *hot) const;
	void GetHOT(const CPoint3F &p, float *hot) const;
	void GetHOT(const CPoint3F *p, float *hot) const;
	void GetHOTFast(const uint x, const uint y, const uint z, float *hot) const;
	void GetHOTFast(const uint index, float *hot) const;

	// use the following interface to get the size of the HOT volume
	uint GetWidth() const { return m_w; }
	uint GetHeight() const { return m_h; }
	uint GetDepth() const { return m_d; }
	uint GetN() const { return m_n; }
	uint GetOrder() const { return m_order; }

	bool HasData() const { 
		if (m_pHOT)
			return true; 
		else
			return false;
	}

	int HOT2Directions_One(const float *hot, CPoint3F *dirs) const;
	int HOT2Directions_Two(const float *hot, CPoint3F *dirs) const;
	int HOT2Directions(const float *hot, CPoint3F *dirs, float *weights = NULL) const;

	float ComputeValue(const float *hot, CVector3F *dir) const;
	float ComputeValue(const float *hot, CVector3F &dir) const;

private:
	float HOTNorm(const float *hot) const;
};

